You can use
Replace[L + L[tilde], L -> 2, {0, Infinity}, Heads -> False]
in this case. Heads -> False is the default, so you don't need to specify it explicitly.
See here for the difference between Replace and ReplaceAll.
Regarding your question about whether it can be done using patterns only, with ReplaceAll or ReplaceRepeated:
First notice that an L -> ... replacement will replace every occurrence of L, regardless of whether it's in a head or not. How can we prevent it from acting on L[_]? The answer: by replacing L[_] before L -> ... has a chance to act:
L + L[tilde] /. {e : L[_] :> e, L -> 2}
Note the ordering of rules: e : L[_] :> e comes first, so it's applied first. Once it's applied, the following rule(s) won't change its result.
Edit from Mr.Wizard
I like to use rule precedence for these kinds of things. (Second method above.) Assuming that we wish to skip L[1,2] as well as L[1] we can use a shorter and faster pattern:
L + L[tilde] /. {x_L :> x, L :> 2}
2 + L[tilde]
Other examples:
A major difference between this method and Replace is that ReplaceAll and Replace traverse the expression in a different order. See (9233). Because of this the rule precedence method will skip expressions with the head L and everything inside them. This may or may not be desirable. The method should be selected based on the specific behavior you desire.