https://sourceware.org/bugzilla/show_bug.cgi?id=12547 contains some info on where this discussion started, basically there is ambiguity in the old interface and rather than trying to rule on a sensible interpretation the standards committee agreed to make the behaviour obscelescent, and then later undefined, as even now at least one BSD seems to refuse to free memory with a size argument of zero.
This was a defect in BSD and the POSIX specification (which literally says it's not intending to contradict the C standard anywhere at the top of every function document), but the committee somehow managed to believe this was cause to deprecate behaviour of realloc() with size zero for 99% of the world. The defect report and associated documents don't seem to be very explicit about the potential impact of the choice to make the behaviour obscelescent in the first place, which might be why this compatibility break was accepted (and eventually completed by making it all undefined).
https://www.open-std.org/jtc1/sc22/wg14/www/docs/summary.htm...
The approach is inconsistent because the committee isn't perfect and every single change to the standard, especially defects, must attempt to best preserve compatibility on a nuanced case-by-case basis, and sometimes when you're in the committee I suspect it's harder to see the wood for the trees. realloc() was broken trying to address a defect report that suggested C's lax definition was potentially a cause of double-frees, a security nightmare, but probably exaggerated in hindsight; and not really made that explicit, although I haven't checked all the minutes and attended the meetings so maybe there was a more conscious decision to deprecate the free-on-zero rule.