I think UML diagrams can only be useful if they express something in a higher level of abstraction than your code.
Writing UML just for the sake of writing UML becomes unneeded bureaucracy and makes the project and the code less adaptable to changes with no benefit whatsoever.
For example, a UML class diagram showing all the classes on a package, with all their attributes and methods --something that can be easily auto-generated-- provides no value at all: it is at the same level of abstraction than your code. Plus, the code will most surely be a better source for that information because it will always be up to date, and it will probably be documented and organized in a way that is easier to know which methods/attributes/things are more important.
On the other hand, if you have concepts of a higher level of abstraction than what can be expressed expressed on the code, documenting those on a diagram can be a good idea.
For example, a diagram showing the higher level abstract modules on a complex system, with their dependencies and maybe a little description of their responsibilities and what package/namespace they map to in the source-code can be a really useful for a new team member that needs to be introduced to the project, or can also be used to figure out where a new class/functionality should be thrown.
Another example of a useful diagram could be a sequence diagram showing the high-level steps to be taken in a communication protocol. Maybe each step of those have it's little quirks and complexities, but it's probably enough to describe them in the code itself. The higher level diagram can help a programmer to understand the "big picture" of things easily without needing to worry about the complexities of each interaction.
Anyway, those are just some examples; there are lots of cases where a simple diagram can be of a lot of help. Just remember that you should be doing them only when you cannot express something in the code itself. If you find yourself using UML diagrams to explain the source-code itself, make the soruce-code more self-documenting instead.
Finally, some of the general rules that apply to code can also apply to diagrams: avoid repeating yourself, keep it simple, don't fear of changing things (just because something is documented on a UML diagram doesn't mean it can't be changed) and always think of who will be reading/maintaining those diagrams in the future (probably your future-self) when writing them :)