The formal description has been already given in the excellent @ColinFine's answer. Let me give a different description in "layman terms".
Mongolian characters usually have four distinct forms: isolate, initial, medial, and final.
Vowels A and E have exactly the same glyphs in their final form.
Here are the four forms for A and E, correspondingly.
Note, both have two versions of final glyphs:

Although choosing between A or E can be concluded from the the syntax (A for masculine grammatic gender while E is for feminine), there can be semantic difference depending on the final form (stroke up or stroke down).
For example:
[qara] (to look), stroke up;
[qar+a] (black), stroke down;
The Vowel Separator is used in the second word.
Phonetically, there's a little pause before the final vowel.
Note that A does not obtain the isolate form. Instead, it only changes to the second final form. Also, R gets the final form in the second word.
As per why the character makes programmers' hell (just in case if you wonder).
Most of the modern-day compilers allows Unicode identifiers (e.g., variable names). You may write your program with variables in your (non-English) language, and your program works just fine.
However, using U+180E may lead you into a trouble because it may or may not be considered a symbol. Here's what happens (assume that X is the Mongolian Vowel Separator):
integer variable aXa = 42;
print aa;
Note: since the X symbol is invisible, the first line on your screen looks like:
integer variable aa = 42;
Trouble one: Unicode versions prior to 4.0 treat X as a formatting (thus, valid) character, but trying to use the variable aa leads you to an error because there is no such variable! There's only aXa, but you can't see it.
Trouble two: Unicode 4.0 treats X as a zero-width space. This means that you're trying to declare a variable with space in its name (a a) which makes your code unable to compile. But again, due to invisibility you simply don't know what's wrong. The code visually looks perfectly valid.
References: