It is interesting to note that without tail recursion, functional programming loses most of its charm. Pure functional languages need recursion to express a lot of common structures. Consider a typical pseudo-C event-handling loop:

for(;;) {
  event = waitForEvent();

  /* do something with the event */
}

Now, the way to write infinite loops in functional programming is through recursion (somewhat inaccurate example):

function handleEvent(event) :
  ( do something with the event )
  handleEvent(getNextEvent())

Now, as you might remember, every function call needs some memory. Notice that this loop will need more memory for each event it processes; which might be acceptable on most recursive algorithms, but an event-handler which runs without the tail recursion optimization will eventually run out of memory.