Tags are ref's that point to specific points in the git history.
Tagging is usually used to capture a point in history that's used for a marked version release (i.e. v1.0.1).
A tag is sort of a branch that does not change.
Unlike branches, tags, once being created, don't have any further history of commits.
From a technical point of view:
tags reside in refs/tags/ namespace and can point to tag objects (annotated and optionally GPG signed tags) or on to commit object (less used light-weight tag for local names), or in very rare cases even to tree object or blob object (e.g. GPG signature).
branches reside in refs/heads/ namespace and may point only to commit objects. The HEAD pointer should refer to a branch (symbolic reference) or on to a commit (detached HEAD or anonymous branch).
remote-tracking branches reside in refs/remotes// namespace and follow ordinary branches in a remote repository.