It's not a valid pointer because you can't use the indirection operator on it. Returning a value other than NULL makes sense because an allocation of size zero is still an allocation.
Additionally the actual amount of memory malloc allocates is implementation-defined so long as it is not less than the amount requested, but accessing this extra memory is undefined behavior since processes don't know if it exists or not. a non-NULL return could be interpreted as malloc(0) allocating more than zero bytes.
Some implementations don't actually perform the allocation until theres a pagefault from the process writing to or reading from that memory so in that sense a non-NULL return is valid too.
I'd argue that malloc(0)==NULL makes less sense because there's no distinction between failure and success.
The only real problem is specifying two alternate behaviors and declaring them both to be equally valid.