I tend to put basic comments as I'm going, just to remind myself what I was thinking at the time when I wrote it (i.e. why I wrote it that way). I do this especially if it's code that looks like it might be wrong but is actually right, or code that has an inherent race condition that I don't care about, or code that might not be optimal but is a quick way to get something working, so that even ten minutes later when I go back and look at it I can see that I've thought about the problem already and don't have to waste any brain cycles on it.
When the code is more complete, I'll often go back and review the comments I've written and then have a think about whether I still think the decisions made are reasonable, and whether things could be done better. I'll also often expand the basic comment into a longer comment that's more useful for other people when they come to maintain the code; I usually save comment expansion to the end because a lot of the time basic comments just get deleted during refactoring, so writing a long comment is a waste of time until you know you're going to keep it.
In a nutshell, write basic comments as you go along, and then improve them as your code becomes more stable.
Oh, and also, any time you review a bit of existing code and you're struck with a WTF?! moment but then realise the code is actually decent, put a comment in to save yourself and the next person time when they look at it in the future.