Disclaimer: some (or maybe all?) of the things I'm mentioning here might be caused by the API itself, rather than the SDK. The order is in which it comes to mind, rather than importance.
1. Some kind of strongly typed errors. I've turned the SDK upside down, and the only error that seems to pop up 90% of the time is CloudError with CloudError data. So our SaaS application (which utilizes Azure IaaS heavily) has a bunch of regexes that parse the messages contained in CloudError and throw something from our domain. Wrapping SDK errors by the implementing clients is a smart thing to do, but not this way :). Some messages change from time to time, so we try to make our regexes more tolerant, but you get the picture. In general the error handling is very strange, a lot of low-level errors sometimes flowing into high-level calls.
2. Documentation with more examples. The easiest thing to do is sometimes looking at the API or CLI documentation, and try replicating it with the SDK. Parameters named differently etc.
3. For some reason the Storage API/SDK keeps changing and it's like it's from another world than compute and network, which look pretty similar. The storage portion is... wild.
4. Improved working with data disks. Updating the VM with an array of disks has shown bad performance (and Azure support helped us and said that it can't be improved because it's a cross-RM event) but also poor reliability. A separate set of methods to attach/detach disks to VMs would be great.
5. Because we heavily rely on asynchronous operations, what we usually do is make a raw HTTP request for an operation (like VM deployment), serialize it and store it, then after some time deserialize it and check if the operation is done. We do the same with hundreds of requests at the same time, being able to process a lot of cloud operations with not much resources on our side :) . It works, but I found the raw request and serialization is a bit clunky. We're also stuck with a couple of older SDK libraries because we've noticed the raw responses changed in the newer ones, so now we need efforts to find all of the differences and consolidate the serialization. For example, the headers have had multiple urls to check the deployment status, sometimes it's `async-url`, sometimes `location-url` etc. This probably isn't something the SDK is to blame, and this is a niche case, but serializable async responses would be nice :D .
I have to commend the effort to break up the libraries from the original SDK into independent units. The versioning and dependency management became easier than with than one monolithic "4.0.0" schema.
Maybe some of the things are out of scope and our use-case is disproportionately affected by some stuff, it's just my two cents. I'm less satisfied with Azure as a service, with its unreliability, sub-par support, idiosyncrasies and poor "hypervisor" performance, than the SDK, but it's the SDK that gets all the blame because it's the one we're interfacing with.