Since the select! macro is designed to await multiple futures/streams in a loop even as some become exhausted, it needs some way to keep track of which futures/streams have already been exhausted so it doesn't await them again. fuse() is one way to do that; it ensures that once a stream is exhausted, it will always be exhausted when polled again. Some futures/streams may already inherently provide this property, so as an optimization, they may implement the FusedStream marker trait manually so that fuse() doesn't have to be used redundantly. On top of that, futures/streams which are polled after exhaustion are allowed to panic or exhibit weird behavior, and fuse() prevents that from happening.
Normally once you call next() on the stream and get a None, you aren't guaranteed that calling .next() again keeps giving you None. Instead, there are some streams that will panic instead if you use them after they have been exhausted. The .fuse() combinator wraps the stream and makes sure that any calls to .next() after the first None will return None again immediately instead of being forwarded to the inner stream.
The futures::select! macro tries to avoid the panics I mentioned by requiring that anything you are selecting over is fused. This is mostly relevant when things are used repeatedly in a loop.