asyncio.coroutine and async def are slightly different—not synonyms. The former defines a generator function and the latter defines a coroutine function. Generators and coroutines are very similar in Python (they share lots of code in the CPython implementation) but coroutines are preferred for async programming. Furthermore, yield from (suspend a generator) and await (suspend a coroutine) are also similar but not synonyms.
It is surprising that Python's async syntax isn't tightly bound to its built-in implementation of asynchronous I/O. This was a shrewd decision that—as others have pointed out—permits a variety of event loop implementations. The downside—as you point out—is that there is no built-in function that can drive an async function.