As mentioned in the previous answer, the difference is that grep is called for each file, and grep does not report the file name if only one file is specified on the command line, if the -H flag (--with-filename).
Why is grep called for every file? This is because (for example, whether it is or not) using the -I (or -i) flag for xargs causes the command to run once for each argument, for example, use the "-L 1" flag for xargs.
On the manual page:
-I replace-str Replace occurrences of replace-str in the initial-arguments with names read from standard input. Also, unquoted blanks do not terminate input items; instead the separator is the newline character. Implies -x and -L 1.
source share