Both codes are wrong (see How to remove items from a list while iterating?), but the symptoms are different in both cases.
In the first case, you're iterating on L. Shortening L makes iteration end faster (notice that some items are skipped, because shortening the list confuses the internal iterator, which raises a StopIteration, which stops the for loop)
You could create some equivalent code of the first case using a while loop:
L = [1, 4, 8, 5]
try:
    i = 0
    while i < len(L):
        print("Item:", L[i])
        del(L[i])
        i += 1
except IndexError as e:
    print("Error:", e)
or emulating the fact that for loop catches the StopIteration exception raised by next on the enumerate iterator:
e = enumerate(L)
while True:
try:
   i,item = next(e)
   print("Value of {} is {}".format(i, item))
   del L[i]
except StopIteration:
    break
you get the same result, because len(L) is evaluated at each iteration, so the index cannot get out of bounds (but the result isn't very useful either)
In the second case, you've computed range(len(L)) with the initial list size. So after a while, the index is out of range for the shortened list.
The first case doesn't crash, but the result is hard to understand, implementation defined, cannot be relied on. Don't do this.