For background, read the introduction.
This is really just a variant of option #2 using the fact that you use azure tables and know that you will get several items at a time. In my opinion you shouldn't even consider this option since it uses a feature of the underlying storage layer and compared to IEnumerable<Task<T>>you do not get any other benefits other than that you create fewer Tasks. Compared to the time it will take you to actually retrieve the data items, the overhead of creating a task for each item is negligible.
In part 2 I briefly mentioned that if you have simple filtering needs then you might implement your own LINQ-like methods. Well if you have more advanced filtering needs there is already something out there to help you; Reactive Extensions (Rx). The only thing you have to do is to expose your data result as an IObservable<T>. So are there no disadvantages with this approach? Well I think there are several.
As you can see; while Rx is a great fit for asynchronous enumerations (because it is what it really is), it uses clever constructs rather than language support to achieve this. Things that are clever often end up complex rather than simple and complex stuff typically breaks. But if your project already uses Rx a lot then it's a no-brainer; use Rx!
This is essentially the opposite of option #1. With this approach you are optimized for processing one item at a time. Or even process all items in parallel! So this is a very good option if you do not need all your data at once and you also have a large number of rows to work on. This option is also very flexible if you have a few scenarios where you actually need all the data since you can always do a Task.WhenAll to wait for all data to be available.
The only big drawback with this approach is filtering using LINQ. Since it is an enumeration of tasks there is no way for you to asynchronously wait for an item in order to for example filter on its value using LINQ. Hence this is not a good option if you need to do a lot of filtering on your items. If you have just a few simple filters it might be worth implementing your own filters like WhereAsync and SelectAsync. All that together miht be worth it given your data and scenarios.
If you need all data before you start processing it or if you expect just a few records each time, then this is probably your simplest way to get an "asynchronous enumeration". Technically the enumeration is not asynchronous since you retrieve all data asynchronously first and then process it. You can also easily use LINQ on the enumeration for processing which is very nice.
The only real drawback is that you're not flexible in case you one day will retrieve a lot of data (or no longer need al data at once for processing). If you have those needs from day one, then this is not the option for you I think.