When you slice a Python list with [start:end] you end up with another list. The beginning of the new list in your example is the location of the last element in your original list. Just because the value of l[-1:0] in your example is [] it does not mean that this is simply an empty list. Its value is an empty list, but the reference to l[-1:0] is to a sliced list within an existing list.
So in your example
l = [1,2,3,4,5]
# ^ l[-1:0] starts here but the size is 0
When you assign a list to a sliced position of another list, you are effectively performing list concatenation.
This is the equivalent of what you are doing.
l=[1,2,3,4,5]
l[4:0] = [99] # concatenate a new list at the position of the final element in the original list
# A different way to look at it
l[0:4] + [99] + l[4:]
The result again is effectively concatenating the two lists. More specifically, you are inserting the elements of a new list into the original at the position you've indicated. Using a literal integer such as 99 will result in an error because you cannot concatenate an int and a list directly. However, as others have pointed out, a slice assignment can use any iterable, so l[-1,0] = (99,) works by the same principle.
[99,]work and not99? Because the object you are assigning a value to is of typelistand not typeint. So what you are technically doing is performing list concatenation at a particular location of your original list.