That makes it a pleasure to code concurrent stuff for IMHO.
It does have its own similar problems though - does a function return an error? If so you are going to need to plumb the error return through all the callers. Does a function need a context.Context? Ditto.
I guess you can't win them all :-)
Author makes up a lie.
Then lampshades it away with a colorful non sequitur.
---
The alternatives that people praise like golang, have other tradeoffs that are much worse because the async logic is now implicit. Your entire codebase is now a surface area that is at risk of being blocked by waiting on a channel; the the mitigation of this is through responsible use of coroutines, but then you're right back around to extra information about your code that is analogous to colring, except not as explicit as async/await.
asyncio.gather is a lot less code than having to manage a thread pool or something like Celery with all it's underlying infrastructure.
If you're in an ecosystem where a lot of the async boilerplate is free/cheap (ex: FastAPI) then the developer overhead of sprinkling awaits on your I/O bound calls is pretty low IMO.
Like, why can't my sync function await something asynchronous? If it has to lock up the whole thread while that function executes, that's fine because that's how it was going to work anyway 99% of the time