The values in a must all be between 1 and  num_embeddings:
for i in range(num_embeddings + 4):
    try:
        embedding(torch.arange(i))
    except:
        print(f"failed for i={i}")

The input data can be any shape:
try:
    embedding(torch.randint(1, num_embeddings, size=(2,3,4,5,6)))
    print("it worked")
except:
    print("this won't print because this won't fail")

Each entry in your input tensor is mapped to a vector with 3 coordinates (a 3-dimensional vector in mathematical terminology, but not in the sense of PyTorch tensors), which can be found in the last axis of the output tensor.  Namely, a[i][j] is mapped to the vector embedding(a)[i][j], which is a 0-dimensional tensor with 3 components.
Interpretation of dimensions
Say for example your input tensor has shape (13, 3), with values between 1 and 10.   If this were to represent text, then you can think of it as having 13 samples of text each containing 3 words each, and each word is taken from a vocabulary of 10 words.