The wait (or sleep) and and releasing the mutex must be atomic to prevent sleep/wakeup races. These are race conditions where a thread is going to sleep at the same time another thread is doing something such that the thread should not go to sleep. Without some mechanism to prevent this type of race, threads can be left in the sleeping state despite having work to do. (See e.g. https://www2.cs.duke.edu/courses/spring00/cps110/slides/sleepcv.pdf .)
Specifically the atomicity guarantees that a pthread_cond_signal or pthread_cond_broadcast that happens after the mutex is released is guaranteed to apply the waiting thread -- i.e. it will be woken up unless a signal woke a different waiting thread.
It is important to understand that condition variables are stateless other than the list of threads waiting on them. If a condition variable is signaled while no threads are waiting, that signal does nothing. Thus if the mutex were released first, another thread could acquire the mutex and then call pthread_cond_signal before the waiting thread was added to the queue and the signal would be missed. The mutex can't be released after as queuing is a blocking operation. (I.e. the thread cannot unlock a mutex while it is asleep, and the sleep call is the thing releasing the mutex must be atomic with.)
There are a number of ways to implement this internally. One is to use some conditional sleep mechanism such as event counters.